package br.com.mftc.efitness.negocio;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.List;

import br.com.mftc.efitness.basicas.PerfilDeUsuario;
import br.com.mftc.efitness.basicas.UsuarioDoSistema;
import br.com.mftc.efitness.dados.DadosUsuarioDoSistema;
import br.com.mftc.efitness.dados.IDadosUsuarioDoSistema;
import br.com.mftc.efitness.excecoes.ExcecaoCamposObrigatoriosNaoPreenchidos;
import br.com.mftc.efitness.excecoes.ExcecaoNegocio;
import br.com.mftc.efitness.util.Util;
import br.com.mftc.efitness.util.Variaveis;

public class ControladorUsuarioDoSistema {
	
	private final IDadosUsuarioDoSistema dadosUsuarioDoSistema;
	
	public ControladorUsuarioDoSistema () {
		dadosUsuarioDoSistema = new DadosUsuarioDoSistema();
	}

	public UsuarioDoSistema efetuarLogin(String login, String senha) throws ExcecaoCamposObrigatoriosNaoPreenchidos, ExcecaoNegocio {
		if (login == null || login.trim().equals("")) {
			throw new ExcecaoCamposObrigatoriosNaoPreenchidos(Variaveis.EXCECAO_INFORME_LOGIN_USUARIO);
		} else if (senha == null || senha.trim().equals("")) {
			throw new ExcecaoCamposObrigatoriosNaoPreenchidos(Variaveis.EXCECAO_INFORME_SENHA_USUARIO);
		} else {
			try {
				UsuarioDoSistema usuarioDoSistema = dadosUsuarioDoSistema.efetuarLogin(login, Util.criptografarSenhaMD5(senha));
				
				if (usuarioDoSistema.getStatusAtivacao() == false) {
					throw new ExcecaoNegocio(Variaveis.EXCECAR_USUARIO_DESATIVADO);
				} else {
					new Thread(new ControladorUsuarioDoSistemaRunnable(usuarioDoSistema, dadosUsuarioDoSistema, ControladorUsuarioDoSistemaRunnable.KEY_ATUALIZAR_HORA_ULTIMO_ACESSO)).start();
					
					return usuarioDoSistema;
				}
			} catch (Exception excecao) {
				if (excecao instanceof NoSuchAlgorithmException || excecao instanceof UnsupportedEncodingException) {
					throw new ExcecaoNegocio(Variaveis.EXCECAO_FALHA_CRIPTOGRAFIA_SENHA);					
				} else {
					throw new ExcecaoNegocio(Variaveis.EXCECAO_FALHA_LOGIN_DADOS_INVALIDOS_USUARIO_NAO_EXISTE);
				}
			}
		}
	}

	public void alterarSenha(UsuarioDoSistema usuarioDoSistema, String senhaAtual, String novaSenha, String confirmeSenha) throws ExcecaoCamposObrigatoriosNaoPreenchidos, ExcecaoNegocio {
		if (usuarioDoSistema == null) {
			throw new ExcecaoCamposObrigatoriosNaoPreenchidos(Variaveis.EXCECAR_USUARIO_ALTERAR_SENHA_INFORME_USUARIO);
		} else if (senhaAtual == null || senhaAtual.trim().equals("")) {
			throw new ExcecaoCamposObrigatoriosNaoPreenchidos(Variaveis.EXCECAR_USUARIO_ALTERAR_SENHA_INFORME_SENHA_ATUAL);
		} else {
			try {
				if (!Util.criptografarSenhaMD5(senhaAtual).equals(usuarioDoSistema.getSenha())) {
					throw new ExcecaoNegocio(Variaveis.EXCECAR_USUARIO_ALTERAR_SENHA_ERRADA_SENHA_ATUAL);
				}
			} catch (NoSuchAlgorithmException | UnsupportedEncodingException excecao) {
				throw new ExcecaoNegocio(Variaveis.EXCECAR_USUARIO_ALTERAR_SENHA_FALHA_VERIFICAR_SENHA_ATUAL);
			}
		}
		if (novaSenha == null || novaSenha.trim().equals("")) {
			throw new ExcecaoCamposObrigatoriosNaoPreenchidos(Variaveis.EXCECAR_USUARIO_ALTERAR_SENHA_INFORME_NOVA_SENHA);
		} else if (novaSenha.length() < UsuarioDoSistema.TAMANHO_MIN_SENHA) {
			throw new ExcecaoNegocio(Variaveis.EXCECAR_USUARIO_ALTERAR_SENHA_NOVA_SENHA_INVALIDA);
		} else if (confirmeSenha == null || confirmeSenha.trim().equals("")) {
			throw new ExcecaoCamposObrigatoriosNaoPreenchidos(Variaveis.EXCECAR_USUARIO_ALTERAR_SENHA_INFORME_CONFIRMACAO_NOVA_SENHA);
		} else if (!novaSenha.equals(confirmeSenha)) {
			throw new ExcecaoNegocio(Variaveis.EXCECAR_USUARIO_ALTERAR_SENHA_SENHAS_NAO_IGUAIS);
		} else {
			try {
				novaSenha = Util.criptografarSenhaMD5(novaSenha);
			} catch (NoSuchAlgorithmException | UnsupportedEncodingException excecao) {
				throw new ExcecaoNegocio(Variaveis.EXCECAR_USUARIO_ALTERAR_SENHA_FALHA_MANIPULAR_NOVA_SENHA);
			}
			try {
				dadosUsuarioDoSistema.iniciarTransacao();
				usuarioDoSistema.setSenha(novaSenha);
				usuarioDoSistema.setDataDeAlteracaoDaSenha(Util.agora());
				usuarioDoSistema.setDataDeUltimaAtualizacao(Util.agora());
				dadosUsuarioDoSistema.alterar(usuarioDoSistema);
				dadosUsuarioDoSistema.finalizarTransacao();
			} catch (Exception excecao) {
				try {
					dadosUsuarioDoSistema.desfazerTransacao();
					throw new ExcecaoNegocio(Variaveis.EXCECAR_USUARIO_ALTERAR_SENHA_FALHA_GRAVAR_NOVA_SENHA);
				} catch (Exception excecaoAux) {
					throw new ExcecaoNegocio(Variaveis.EXCECAR_USUARIO_ALTERAR_SENHA_FALHA_GRAVAR_NOVA_SENHA);
				}
			}
		}
	}
	
	public List<UsuarioDoSistema> consultarPorPerfil(PerfilDeUsuario perfilDeUsuario) throws ExcecaoNegocio {
		try {
			return dadosUsuarioDoSistema.consultarPorPerfil(perfilDeUsuario);
		} catch (Exception excecao) {
			throw new ExcecaoNegocio(Variaveis.EXCECAR_USUARIO_CONSULTAR_POR_PERFIL);
		}
	}
}

class ControladorUsuarioDoSistemaRunnable implements Runnable {

	UsuarioDoSistema usuarioDoSistema;
	IDadosUsuarioDoSistema dadosUsuarioDoSistema;
	
	int key;
	
	static final int KEY_ATUALIZAR_HORA_ULTIMO_ACESSO = 1;
	
	ControladorUsuarioDoSistemaRunnable (UsuarioDoSistema usuarioDoSistema, IDadosUsuarioDoSistema dadosUsuarioDoSistema, int key) {
		this.usuarioDoSistema = usuarioDoSistema;
		this.dadosUsuarioDoSistema = dadosUsuarioDoSistema;
		this.key = key;
	}
	
	@Override
	public void run() {
		switch (key) {
		case KEY_ATUALIZAR_HORA_ULTIMO_ACESSO:
			try {
				dadosUsuarioDoSistema.iniciarTransacao();
				
				usuarioDoSistema.setDataDeUltimoAcesso(Util.agora());
				usuarioDoSistema.setDataDeUltimaAtualizacao(Util.agora());
				
				dadosUsuarioDoSistema.alterar(usuarioDoSistema);
				dadosUsuarioDoSistema.finalizarTransacao();
			} catch (Exception excecao) {
				try {
					dadosUsuarioDoSistema.desfazerTransacao();
					System.err.println(excecao.getMessage());
				} catch (Exception excecaoAux) {
					System.err.println(excecaoAux.getMessage());
				}
			}
			break;
		default:
			break;
		}
	}
}
